using System;
using System.Drawing;
using ShadeTree.Binding.Drivers;
using ShadeTree.Binding.Stylers;

namespace ShadeTree.Binding.Elements
{
    
    public class ScreenElement<T> : IScreenElement
    {
        private readonly IControlDriver _driver;
        private ActivationMode _activationMode;
        private string _alias;
        private IControlDriver _label;
        private IControlDriver _postLabel;
        private readonly Color _originalColor;
        private readonly T _boundControl;

        private Action<object> _showAction = (target) => { };
        private Action<object> _enableAction = (target) => { };

        

        public ScreenElement(T control)
        {
            _driver = ControlDriverFactory.GetDriver(control);
            Styler.Default.ApplyStyle(control);
            _originalColor = _driver.BackColor;
            _boundControl = control;
        }

        protected IControlDriver driver
        {
            get { return _driver; }
        }

        public T BoundControl
        {
            get { return _boundControl; }
        }

        public virtual void Highlight(Color color)
        {
            _driver.BackColor = color;
        }

        public virtual void RemoveHighlight()
        {
            _driver.BackColor = _originalColor;
        }

        #region IScreenElement Members

        public void Hide()
        {
            _driver.Visible = false;
            if (_label != null) _label.Visible = false;
            if (_postLabel != null) _postLabel.Visible = false;
        }

        public void Show()
        {
            _driver.Visible = true;
            if (_label != null) _label.Visible = true;
            if (_postLabel != null) _postLabel.Visible = true;
        }

        public void CopyFrom(IScreenDriver driver)
        {
            IScreenElement peer = driver.FindElementForControl(_driver.Control);
            if (peer != null) CopyFrom(peer);
        }

        public object Control
        {
            get { return _driver.Control; }
        }

        public ActivationMode ActivationMode
        {
            get { return _activationMode; }
            set
            {
                _activationMode = value;
                if (_activationMode == Binding.ActivationMode.ReadOnly)
                {
                    Disable();
                }
            }
        }


        public string Alias
        {
            get { return _alias; }
            set { _alias = value; }
        }

        public IControlDriver Label
        {
            get { return _label; }
            set { _label = value; }
        }

        public IControlDriver PostLabel
        {
            get { return _postLabel; }
            set { _postLabel = value; }
        }

        public virtual void EnableControl(IScreenState state)
        {
            switch (_activationMode)
            {
                case ActivationMode.ReadOnly:
                    Disable();
                    break;

                case ActivationMode.AlwaysActive:
                    Enable();
                    break;

                case ActivationMode.Normal:
                    if (state.IsControlEnabled(_driver.Control))
                    {
                        Enable();
                        postEnable();
                    }
                    else
                    {
                        Disable();
                    }

                    break;
            }
        }

        protected virtual void postEnable()
        {
            
        }

        public void Enable()
        {
            _driver.Enabled = true;
        }

        public void Disable()
        {
            _driver.Enabled = false;
        }

        public string ToolTipText
        {
            get { return _driver.ToolTipText; }
            set { _driver.ToolTipText = value; }
        }

        public bool Matches(string labelText)
        {
            if (_label != null && _label.Text == labelText)
            {
                return true;
            }

            if (!string.IsNullOrEmpty(_alias))
            {
                return _alias == labelText;
            }

            return false;
        }

        public virtual void Focus()
        {
            _driver.Focus();
        }


        public string LabelText
        {
            get
            {
                if (!string.IsNullOrEmpty(_alias))
                {
                    return _alias;
                }

                if (_label != null)
                {
                    return _label.Text;
                }

                return string.Empty;
            }
        }

        #endregion

        public void CopyFrom(IScreenElement element)
        {
            _label = element.Label;
            _alias = element.Alias;
            _postLabel = element.PostLabel;
        }

        public void UpdateDisplayState(object target)
        {
            _showAction(target);
            _enableAction(target);
            afterUpdateDisplay(target);
        }

        protected virtual void afterUpdateDisplay(object target)
        {
        }

        public void BindVisibilityTo(Accessor accessor)
        {
            _showAction = (target) =>
                          {
                              bool isVisible = (bool) accessor.GetValue(target);
                              if (isVisible) Show();
                              if (!isVisible) Hide();
                          };
        }

        public void BindEnabledTo(Accessor accessor)
        {
            _enableAction = (target) =>
            {
                bool isEnabled = (bool)accessor.GetValue(target);
                if (isEnabled) Enable();
                if (!isEnabled) Disable();
            };
        }
    }
}